package von.seiji.cn.test;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.beust.jcommander.internal.Lists;
import org.junit.Test;
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.videoio.VideoCapture;
import org.opencv.videoio.VideoWriter;
import org.opencv.videoio.Videoio;
import von.seiji.cn.PointUtil;

import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class 人头识别 {

    static {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
//        URL resource = T1.class.getClassLoader().getResource("data/opencv_videoio_ffmpeg430_64.dll");
        System.load("D:\\seiji926\\workspace\\idea\\other\\seiji2util\\src\\main\\resources\\data\\opencv_videoio_ffmpeg430_64.dll");
       /* try {
            //System.load("/root/opencv_build/opencv/build/lib/libopencv_java430.so");
            System.load(URLDecoder.decode(resource.getPath(), Charset.defaultCharset().name()));
        } catch (Exception e) {
            e.printStackTrace();
        }*/
    }

    @Test
    public void threadL() {
        List<String> strings = Lists.newArrayList(
                "东区负二层换乘大厅出站口  9_20210720164109至20210720165229",
                "东区负二层换乘大厅出站口  9_20210720165231至20210720170352",
                "东区负二层换乘大厅出站口  9_20210720170354至20210720171107",
                "西区负二层出租车上客区2  90_20210719084034至20210719090341",
                "西区负二层出租车上客区2  90_20210719090345至20210719091029",
                "西区负一层公交车道3  116_20210806142014-20210806145014_1");

        List<int[]> ints = Lists.newArrayList(new int[]{969, 483},
                new int[]{1583, 479},
                new int[]{2177, 1295},
                new int[]{389, 1295});
        List<Point> collect = ints.stream().map(item -> new Point(item[0], item[1])).collect(Collectors.toList());

        List<int[]> ints1 = Lists.newArrayList(new int[]{667, 513},
                new int[]{1113, 347},
                new int[]{2489, 867},
                new int[]{2273, 1405},
                new int[]{909, 1407});
        List<Point> collect1 = ints1.stream().map(item -> new Point(item[0], item[1])).collect(Collectors.toList());
        List<int[]> ints2 = Lists.newArrayList(new int[]{1459, 535},
                new int[]{1905, 631},
                new int[]{1825, 1415},
                new int[]{763, 1365});
        List<Point> collect2 = ints2.stream().map(item -> new Point(item[0], item[1])).collect(Collectors.toList());

        List<List<Point>> lists = Lists.newArrayList(collect, collect, collect,
                collect1, collect1, collect2);

//        test34(strings.get(5), lists.get(5));

//        IntStream.range(0, strings.size()).forEach(index -> {
           /* Thread thread = new Thread(() -> {
                test34(strings.get(index), lists.get(index));
            });*/
            new Thread(new Runnable(){
                @Override
                public void run() {
                    test34(strings.get(0), lists.get(0));
                }
            }).start();
          /*  thread.setName(strings.get(index));
//            thread.start();*/
//        });

       /* for (int i = 0; i < strings.size(); i++) {
            final int index = i;
            Thread thread = new Thread(() -> {
                test34(lists.get(index));
            });
            thread.setName(strings.get(i));
            thread.start();
        }*/

    }


    String ipath = "D:/LL/{}.mp4";


    String opath = "D:/LL/区域识别人头/{}.avi";

//    @Test
    public void test34(String name, List<Point> pointList) {
//        String name = Thread.currentThread().getName();
//        System.out.println("当前线程名称：" + name);
        long l = System.currentTimeMillis();
        VideoCapture capture = new VideoCapture();
//        capture.open(0); 本地摄像头
        // rtsp://admin:12345@192.0.0.64:554/h264/ch1/main/av_stream
//        String path = "rtsp://admin:a12345678@192.168.1.64:554/Streaming/Channels/101?transportmode=unicast";
//        capture.open(path);

        String path = StrUtil.format(ipath, name);
        capture.open(path);
        if (!capture.isOpened()) {
            System.out.println("could not load video data...");
            return;
        }
        int frame_width = (int) capture.get(3);
        int frame_height = (int) capture.get(4);
        ImageGUI gui = new ImageGUI();
        // gui.createWin("OpenCV + Java视频读与播放演示", new Dimension(frame_width, frame_height));
//        gui.createWin("OpenCV + Java视频读与播放演示");
        Mat frame = new Mat();

//        String baseImg = "C:\\Users\\Administrator\\Documents\\baseImg.jpg";

        //penCV 下载包含动态链接库文件 opencv_ffmpeg343_64.dll 中的 mp
       /* System.setProperty("java.library.path", "C:\\pathToFolderContainingDLL");
        val fieldSysPath = ClassLoader::class.java.getDeclaredField("sys_paths")
        fieldSysPath.isAccessible = true
        fieldSysPath.set(null, null)*/
//next time path is accessed, the new path will be imported

//        System.loadLibrary("opencv_ffmpeg343_64")

        Size size = new Size(capture.get(Videoio.CAP_PROP_FRAME_WIDTH), capture.get(Videoio.CAP_PROP_FRAME_HEIGHT));
        double fps = capture.get(Videoio.CAP_PROP_FPS);
        System.out.println("fps = " + fps);
        VideoWriter vw = new VideoWriter(StrUtil.format(opath, name), VideoWriter.fourcc('M', 'J', 'P', 'G'), 25, size, true);

int count = 0;
        while (true) {

            if(count ++ % 4 == 0) continue;

            boolean have = capture.read(frame);
            // Core.flip(frame, frame, 1);// Win上摄像头
            if (!have) break;
            if (!frame.empty()) {
//                BufferedImage bufferedImage = convert2Image(frame);

                Mat mat = new Mat();
                frame.copyTo(mat);

               /* double i = PicCompare.compareHistogram(baseImg, mat);
                System.out.println("相似度："+ i);*/
                byte[] bytes = mat2Byte(frame, JPG);

//                FileUtil.writeBytes(bytes,baseImg);


                head_resolve(Base64.encode(bytes), frame, pointList);
                System.out.println("===================================================");
//                gui.imshow(convert2Image(frame));
                vw.write(frame);


                long l1 = System.currentTimeMillis();

                System.out.println("已耗时：" + (l1 - l) / 1000 + "秒");

             /*   try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }*/
            } else {
                System.err.println("----------------->结束");
                break;
            }
        }
    }

    public static Mat byte2Mat(byte[] bytes) {
        return Imgcodecs.imdecode(new MatOfByte(bytes), Imgcodecs.IMREAD_UNCHANGED);
    }

    public static final String JPG = ".jpg";
    public static final String PNG = ".png";

    public static byte[] mat2Byte(Mat mat, String ext) {
        MatOfByte aByte = new MatOfByte();
        Imgcodecs.imencode(ext, mat, aByte);
        return aByte.toArray();
    }


    /**
     * 人头识别
     *
     * @param
     * @return
     */

    public void head_resolve(String image, Mat frame, List<Point> collect) {
        String url = "http://192.168.1.16:20006";
        JSONObject param = new JSONObject();
        param.put("image", image);
//        param.put(CommonConst.TOP_NUM, 27);
        String post = HttpRequest.post(url).body(param.toString(), ContentType.JSON.getValue()).execute().body();
        JSONObject parse = (JSONObject) JSON.parse(post);
        System.out.println("---------------------------------------------------------");
//        System.out.println("返回数据：" + parse);

        // -------------------------------------------------------------------------
       /* int ileft = 215;
        int itop = 163;
        int iright = 1275;
        int ibottom = 1423;


        // 矩形区域
        Imgproc.rectangle(frame, new Point(ileft, itop), new Point(iright, ibottom)
                , new Scalar(0, 255, 0), 3);*/
        //任意四边形
        /*List<int[]> ints = Lists.newArrayList(new int[]{759, 173},
                new int[]{2421, 841},
                new int[]{2369,1403},
                new int[]{911,1403},
                new int[]{599, 413});*/
       /* List<int[]> ints = Lists.newArrayList(new int[]{969, 579},
                new int[]{1623, 569},
                new int[]{2177, 1345},
                new int[]{419, 1321});
        List<Point> collect = ints.stream().map(item -> new Point(item[0], item[1])).collect(Collectors.toList());*/
//        JSONArray jsonArray = (JSONArray) JSON.toJSON(collect);
        line_polygon(frame, collect, new Scalar(255, 0, 0), 2);
        System.out.println("绘制区域完成");


        JSONArray results = parse.getJSONArray("results");
        System.out.println("检测到总人数：" + results.size());


        long count = results.stream().filter(item -> {
            JSONObject item1 = (JSONObject) item;

            JSONObject location = item1.getJSONObject("location");
            int left = location.getIntValue("left");
            int top = location.getIntValue("top");
            int width = location.getIntValue("width");
            int height = location.getIntValue("height");
            int right = location.getIntValue("left") + width;
            int bottom = location.getIntValue("top") + height;

            Point target = new Point(left + width / 2, top + height / 2);


            if (PointUtil.polygonJudge(target, collect)) {

                Imgproc.rectangle(frame, new Point(left, top), new Point(right, bottom)
                        , new Scalar(0, 0, 255), 1);
                return true;
            }
            return false;

           /* Imgproc.line(frame, new Point(left, top), new Point(right, bottom)
                    , new Scalar(0,0,255));*/
        }).count();

//        Imgcodecs.imwrite("D:\\LL\\img\\" + System.currentTimeMillis() + ".jpg", frame);
        System.out.println("目标区域内人数：" + count);

    }


    public static BufferedImage convert2Image(Mat matrix) {
        int type = BufferedImage.TYPE_BYTE_GRAY;
        if (matrix.channels() > 1) {
            type = BufferedImage.TYPE_3BYTE_BGR;
        }
        int bufferSize = matrix.channels() * matrix.cols() * matrix.rows();
        byte[] buffer = new byte[bufferSize];
        matrix.get(0, 0, buffer);
        // 获取所有的像素点
        BufferedImage image = new BufferedImage(matrix.cols(), matrix.rows(), type);
        final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
        System.arraycopy(buffer, 0, targetPixels, 0, buffer.length);
        return image;
    }

    public static void line_polygon(Mat mat, List<Point> pointList, Scalar scalar, int thickness) {
        IntStream.range(0, pointList.size()).forEach(index -> {
            Point point = pointList.get(index % pointList.size());
            Point point1 = pointList.get((index + 1) % pointList.size());
            Imgproc.line(mat, point, point1, scalar, thickness);
        });

    }


 /*     public static BufferedImage convert2Image(Mat mat) {
        int width = mat.cols();
        int height = mat.rows();
        int dims = mat.channels();
        int[] pixels = new int[width * height];
        byte[] rgbdata = new byte[width * height * dims];
        mat.get(0, 0, rgbdata);
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        int index = 0;
        int r = 0, g = 0, b = 0;
        for (int row = 0; row < height; row++) {
            for (int col = 0; col < width; col++) {
                if (dims == 3) {
                    index = row * width * dims + col * dims;
                    b = rgbdata[index] & 0xff;
                    g = rgbdata[index + 1] & 0xff;
                    r = rgbdata[index + 2] & 0xff;
                    pixels[row * width + col] = ((255 & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | b & 0xff;
                }
                if (dims == 1) {
                    index = row * width + col;
                    b = rgbdata[index] & 0xff;
                    pixels[row * width + col] = ((255 & 0xff) << 24) | ((b & 0xff) << 16) | ((b & 0xff) << 8) | b & 0xff;
                }
            }
        }
        setRGB(image, 0, 0, width, height, pixels);
        return image;
    }

        public static void setRGB(BufferedImage image, int x, int y, int width, int height, int[] pixels) {
        int type = image.getType();
        if (type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB)
            image.getRaster().setDataElements(x, y, width, height, pixels);
        else
            image.setRGB(x, y, width, height, pixels, 0, width);
    }*/



    /*  byte * matToBytes(Mat image)
    {
        int size = image.total() * image.elemSize();
        byte * bytes = new byte[size];  // you will have to delete[] that later
        std::memcpy(bytes,image.data,size * sizeof(byte));
    }




    Mat bytesToMat(byte * bytes,int width,int height)
    {
        Mat image = Mat(height,width,CV_8UC3,bytes).clone(); // make a copy
        return image;
    }
    */

}
